
package com.lmx.persistence.service;

import com.lmx.common.context.ActionContextHolder;
import com.lmx.common.util.CommonUtil;
import com.lmx.common.util.HttpRequestUtil;
import com.lmx.common.util.PropertiesFileUtil;
import com.lmx.repoDomain.tmodel.WeChatInfo;
import com.lmx.repoDomain.tmodel.weixin.TemplateData;
import com.lmx.repoDomain.tmodel.weixin.WeixinAccessToken;
import com.lmx.repoDomain.tmodel.weixin.WxTemplate;

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * 
 * 
 * @author huibati
 * @version 1.00
 */
@Service
@Scope("prototype")
public class WeiXinService<T> {

	private Log logger = LogFactory.getLog(this.getClass());

	private Properties properties = PropertiesFileUtil.getApplicationProperties();

	@PersistenceContext
	private EntityManager em;

	@Autowired
	protected GenericService dslJpaService;

	/**
	 * 获取微信公众号平台接口的ACCESS_TOKEN
	 * 
	 * @return
	 */
	public String getWeixinAccessToken() {
		if (ActionContextHolder.getWatHolder().get("accessToken") != null) {
			WeixinAccessToken tempToken = (WeixinAccessToken) ActionContextHolder.getWatHolder().get("accessToken");
			Long tLong = System.currentTimeMillis();
			logger.debug("WeixinAccessToken  date compare " + tLong + " now");
			logger.debug("WeixinAccessToken  date compare " + tempToken.getExpirationTime() + " deadline");
			if (tLong > tempToken.getExpirationTime()) {// 超过时限 重新请求
				String token = getAccessToken();
				logger.debug("WeixinAccessToken  token  date " + token);
				return token;
			} else {// 时限之内 复取数据
				logger.debug("WeixinAccessToken  token " + tempToken.getAccessToken());
				return tempToken.getAccessToken();
			}
		} else {
			String token = getAccessToken();
			logger.debug("WeixinAccessToken  token  null " + token);
			return token;
		}
	}

	private String getAccessToken() {
		String appId = properties.getProperty("weixin.appId");
		String appSecret = properties.getProperty("weixin.appSecret");

		String url = properties.getProperty("weixin.getToken");
		// https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+appSecret
		// https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=
		String returnData = HttpRequestUtil.sendGet(url,
				"grant_type=client_credential&appid=" + appId + "&secret=" + appSecret);
		JSONObject json = JSONObject.fromObject(returnData);
		logger.debug("WeixinAccessToken  get response  " + json.toString());
		if (json.containsKey("access_token")) {
			if (json.get("access_token") != null && !json.get("access_token").equals("")) {
				WeixinAccessToken temp = new WeixinAccessToken();
				temp.setAccessToken((json.get("access_token").toString()));
				temp.setExpirationTime(
						System.currentTimeMillis() + Integer.parseInt(json.get("expires_in").toString()) * 1000);
				logger.debug("  WeixinAccessToken    get  " + temp.getExpirationTime() + "  " + temp.getAccessToken());
				ActionContextHolder.getWatHolder().put("accessToken", temp);
				return json.get("access_token").toString();
			}
		}
		return null;
	}

	/* 生成永久二维码 */
	public String getPerpetualQR(String uid) {
		// 获取数据的地址
		String createUrl = properties.getProperty("weixin.createQRcode") + getWeixinAccessToken();
		// 发送给微信服务器的数据
		String jsonStr = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\"：{\"scene\": {\"scene_id\": " + uid
				+ "}}}";
		String response = HttpRequestUtil.sendPost(createUrl, jsonStr);
		JSONObject json = JSONObject.fromObject(response);
		if (json.containsKey("ticket")) {
			return properties.getProperty("weixin.showQRcode") + json.get("ticket").toString();
		} else {
			return null;
		}
	}

	/**
	 * 获取微信JSSDK的ticket
	 * 
	 * @author Benson
	 */
	public String getJSSDKTicket() {
		String url = properties.getProperty("weixin.JssdkTicket");
		String token = getWeixinAccessToken();
		String returnData = HttpRequestUtil.sendGet(url, "access_token=" + token + "&type=jsapi");
		JSONObject json = JSONObject.fromObject(returnData);
		logger.debug("getJSSDKTicket token:" + token + " getJSSDKTicket:" + json);
		if (json.containsKey("ticket")) {
			return json.get("ticket").toString();
		} else {
			return null;
		}

	}

	/**
	 * @author huibati 获取微信timestamp,nonceStr,signature
	 * @param 2017年6月29日
	 */
	public WeChatInfo sign(String url) {
		String jsapi_ticket = getJSSDKTicket();
		Map<String, String> ret = new HashMap<String, String>();
		String nonce_str = CommonUtil.create_nonce_str();
		String timestamp = CommonUtil.create_timestamp();
		String string1;
		String signature = "";
		// 注意这里参数名必须全部小写，且必须有序
		string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;
		// logger.debug("sign url jsapi_ticket "+string1);
		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(string1.getBytes("UTF-8"));
			signature = byteToHex(crypt.digest());
		} catch (Exception e) {
			logger.debug("weixin sign error " + e);
		}
		// ret.put("url", url);
		// ret.put("jsapi_ticket", jsapi_ticket);
		// ret.put("nonceStr", nonce_str);
		// ret.put("timestamp", timestamp);
		// ret.put("signature", signature);
		WeChatInfo info = new WeChatInfo();
		info.setAppId(properties.getProperty("weixin.appId"));
		info.setNonceStr(nonce_str);
		info.setSignature(signature);
		info.setTimeStamp(timestamp);
		info.setJsapiTicket(jsapi_ticket);
		info.setId((long) 1);
		logger.debug(
				"sign url jsapi_ticket " + string1 + "  appid:" + info.getAppId() + " sign:" + info.getSignature());
		return info;
	}

	private static String byteToHex(final byte[] hash) {
		Formatter formatter = new Formatter();
		for (byte b : hash) {
			formatter.format("%02x", b);
		}
		String result = formatter.toString();
		formatter.close();
		return result;
	}

	/**
	 * 拼接获取code的url
	 * 
	 * @author Benson
	 */
	public String getCodeUrl(String redirect_uri) {
		String appid = properties.getProperty("weixin.appId"); // 微信appid

		// scope 参数视各自需求而定，这里用scope=snsapi_base 不弹出授权页面直接授权目的只获取统一支付接口的openid
		String url = "";
		try {
			url = properties.getProperty("weixin.oauth2Code") + appid + "&redirect_uri="
					+ URLEncoder.encode(redirect_uri, "UTF-8")
					// + redirect_uri
					+ "&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
		} catch (UnsupportedEncodingException e) {
			logger.debug("getCodeUrl error " + e);
		}
		return url;
	}

	/**
	 * 拼接获取openid
	 * 
	 * @author huibati
	 * @param 2017年6月29日
	 */
	public String getOpenIDByCode(String code) {
		String appID = properties.getProperty("weixin.appId"); // 微信appid
		String appSecret = properties.getProperty("weixin.appSecret");
		String url = properties.getProperty("weixin.oauth2OpenId");
		for (int i = 0; i < 5; i++) {
			String returnData = HttpRequestUtil.sendGet(url,
					"appid=" + appID + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code");
			JSONObject js = JSONObject.fromObject(returnData);
			logger.debug("weixin openId res: "+js);
			if (js.containsKey("openid") && null != js.getString("openid") && !"".equals(js.getString("openid")))
				return js.getString("openid");
		}
		return "";
	}

	/**
	 * 发送模板消息 appId 公众账号的唯一标识 appSecret 公众账号的密钥 openId 用户标识
	 * 
	 * @throws Exception
	 */
	public void send_template_message(String openId, HashMap<String, String> tempData, String urlData,String templateID) throws Exception {
		String access_token = getWeixinAccessToken();
		String url = properties.getProperty("weixin.template_msg_url") + access_token;
		WxTemplate temp = new WxTemplate();
		temp.setUrl(urlData);
		temp.setTouser(openId);
		temp.setTopcolor("#000000");
		temp.setTemplate_id(templateID);
		Map<String, TemplateData> m = new HashMap<String, TemplateData>();
		for (Iterator<String> itr = tempData.keySet().iterator(); itr.hasNext();) {
			String key = (String) itr.next();
			String value = (String) tempData.get(key);
			TemplateData data = new TemplateData();
			data.setColor("#000000");
			data.setValue(value);
			m.put(key, data);
		}
		temp.setData(m);
		String jsonString = JSONObject.fromObject(temp).toString();
		JSONObject jsonObject = HttpRequestUtil.httpRequest(url, "POST", jsonString);
		int result = 0;
		if (null != jsonObject) {
			if (0 != jsonObject.getInt("errcode")) {
				result = jsonObject.getInt("errcode");
				logger.error("template message errcode:{} errmsg:{} " + jsonObject.getInt("errcode") + " "
						+ jsonObject.getString("errmsg"));
			}
		}
		logger.info("send weixin template message：" + result);
	}
}
